#include <iostream>
#include <functional>
using namespace std;

/*
    1. 无参数，无返回值的lambda表达式

    [捕获列表] (参数列表) -> 返回类型 {
    // 函数体
    };
    2. auto推导返回值的lambda表达式
    auto [捕获列表] (参数列表) -> 返回类型 {
    // 函数体
    };

    3. 有参数，有返回值的lambda表达式
    std::function<int(int, int)> func =[捕获列表] (参数列表) -> 返回类型 
    {
        // 函数体
    };
*/

    



 int main()
{

    // 无参数，无返回值的lambda表达式
    []()
    {
        cout << "这是无参数，无返回值的lambda表达式" << endl;
    }();    // 这种写法能适用于 直接立即调用的情况，不能等到后面你想调用再调用


    // auto 关键字可以自动推导lambda表达式的返回类型
    auto func1 = []() -> int
    {
        cout << "这是用auto关键字可以自动推导lambda表达式的返回类型" << endl;
        return 0;
    };

    int a1 = 10;
    int a2 = 30;
    int a3 = 50;
    int a4 = 70;

    // 用std::function 来存储lambda表达式
    //指定变量进行捕获，但是默认在匿名函数内不能更改，如果想更改用mutable关键字
    std::function<int()> func2 = [a1]() -> int
    {
        cout << "这是用std::function 来存储的lambda表达式" << endl;
        return 0;
    };

    // 用mutable关键字可以在匿名函数内更改捕获的变量
    std::function<int()> func3 = [a1]() mutable -> int
    {
        cout << "这是用mutable关键字可以在匿名函数内更改捕获的变量" << endl;
        a1 = 20;
        cout << "a1的值为: " << a1 << endl;
        return 0;
    };

    // 用引用捕获可以在匿名函数内更改捕获的变量
    std::function<int()> func4 = [&a2]() -> int
    {
        cout << "这是用引用捕获可以在匿名函数内更改捕获的变量" << endl;
        a2 = 40;
        cout << "a2的值为: " << a2 << endl;
        return 0;
    };

    // 用值捕获可以在匿名函数内更改捕获的变量
    std::function<int()> func5 = [&]() -> int
    {
        cout << "这是用捕获列表可以在匿名函数内更改捕获的变量" << endl;
        a3 = 60;
        cout << "a3的值为: " << a3 << endl;
        a4 = 80;
        cout << "a4的值为: " << a4 << endl;
        return 0;
    };

    // [=] 没有指定固定值捕获的变量，默认用值捕获
    std::function<int()> func6 = [=]() -> int
    {
        cout << "这是用[=]没有指定固定值捕获的变量，默认用值捕获" << endl;
        cout << "a1的值为: " << a1 << endl;
        cout << "a2的值为: " << a2 << endl;
        cout << "a3的值为: " << a3 << endl;
        cout << "a4的值为: " << a4 << endl;
        return 0;
    };

    


    func1();
    func2();
    func3();
    func4();
    func5();

    return 0;
}